| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103 |
- import { fetchJson } from '@/lib/utils/server';
- import { ResultDto } from '@/types/response/common';
- import { ChannelDetail } from '@/types/channel';
- import { notFound } from 'next/navigation';
- import Link from 'next/link';
- import './style.scss';
- type Props = {
- params: Promise<{ channelSID: string }>;
- };
- function formatCount(n: number): string {
- if (n >= 10000) return `${(n / 10000).toFixed(n >= 100000 ? 0 : 1)}만`;
- if (n >= 1000) return `${(n / 1000).toFixed(1)}천`;
- return n.toLocaleString();
- }
- export default async function ChannelPage({ params }: Props) {
- const { channelSID } = await params;
- const res: ResultDto<ChannelDetail> = await fetchJson(`/api/channel/${channelSID}`, { method: 'GET' });
- if (!res.data) {
- notFound();
- }
- const ch = res.data;
- return (
- <div className="channel-page">
- {/* 배너 */}
- <div className="channel-page__banner">
- {ch.bannerUrl && (
- <img
- src={`${ch.bannerUrl}=w1707-fcrop64=1,00005a57ffffa5a8-k-c0xffffffff-no-nd-rj`}
- alt={`${ch.name} 배너`}
- className="channel-page__banner-img"
- />
- )}
- </div>
- {/* 프로필 */}
- <div className="channel-page__profile">
- {/* 썸네일 */}
- <a href={ch.youTubeUrl} target="_blank" rel="noopener noreferrer" className={`channel-page__avatar${ch.isLive ? ' channel-page__avatar--live' : ''}`}>
- {ch.thumbnailUrl ? (
- <img src={ch.thumbnailUrl} alt={ch.name} />
- ) : (
- <div className="channel-page__avatar-placeholder">{ch.name.charAt(0)}</div>
- )}
- {ch.isLive && <span className="channel-page__live-badge">LIVE</span>}
- </a>
- {/* 채널명 + 메타 */}
- <div className="channel-page__info">
- <h1 className="channel-page__name">
- <a href={ch.youTubeUrl} target="_blank" rel="noopener noreferrer">{ch.name}</a>
- {ch.isVerified && <span className="channel-page__verified" title="인증됨">✓</span>}
- </h1>
- <div className="channel-page__meta">
- {ch.handle && <span>@{ch.handle}</span>}
- {(ch.subscriberCount ?? 0) > 0 && <span>구독자 {formatCount(ch.subscriberCount)}명</span>}
- {(ch.videoCount ?? 0) > 0 && <span>동영상 {ch.videoCount.toLocaleString()}개</span>}
- </div>
- {/* 데스크톱 전용: 메타 아래 인라인 */}
- <div className="channel-page__buttons channel-page__buttons--desktop">
- <a href={ch.youTubeUrl} target="_blank" rel="noopener noreferrer" className="channel-page__subscribe-btn">구독</a>
- <Link href={`/donation/${ch.channelSID}`} className="channel-page__donate-btn">후원하기</Link>
- </div>
- </div>
- </div>
- {/* 모바일 전용: 프로필 아래 별도 줄 */}
- <div className="channel-page__buttons channel-page__buttons--mobile mt-3">
- <a href={ch.youTubeUrl} target="_blank" rel="noopener noreferrer" className="channel-page__subscribe-btn">구독</a>
- <Link href={`/donation/${ch.channelSID}`} className="channel-page__donate-btn">후원하기</Link>
- </div>
- {/* 라이브 상태 */}
- {ch.isLive && (
- <div className="channel-page__live">
- <span className="channel-page__live-dot" />
- <span className="channel-page__live-title">{ch.liveTitle}</span>
- <Link href={`/watch/${ch.channelSID}`} className="channel-page__watch-btn">방송 보러가기 →</Link>
- </div>
- )}
- {/* 탭 네비게이션 */}
- <nav className="channel-page__tabs">
- <span className="channel-page__tab channel-page__tab--active">소개</span>
- <span className="channel-page__tab">게시물</span>
- </nav>
- {/* 소개 탭 콘텐츠 */}
- <div className="channel-page__tab-content">
- {ch.description ? (
- <p className="channel-page__description">{ch.description}</p>
- ) : (
- <p className="channel-page__empty">채널 소개가 없습니다</p>
- )}
- </div>
- </div>
- );
- }
|